package com.ssh.demo.jschsshdemo.Shell;


import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;


import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class ExecShellUtil {


    public static void executeByOrder(List<String> cmdList) {


    }


    public static boolean simpleCmd(String cmd) {
        ProcessBuilder builder = new ProcessBuilder("/bin/sh", "-c", cmd);
        builder.directory();
        int runningStatus;
        String s;
        Process p = null;
        try {
            p = builder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
        assert p != null;
        try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
             BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()))) {
            while ((s = stdInput.readLine()) != null) {
                log.info("shell log info ...." + s);
                log.info("\r\n");
            }
            while ((s = stdError.readLine()) != null) {
                log.error("shell log error...." + s);
                log.error("\r\n");
            }
            try {
                runningStatus = p.waitFor();
            } catch (InterruptedException e) {
                runningStatus = 1;
                log.error("等待shell脚本执行状态时，报错...", e);
            }
        } catch (Exception e) {
            log.error("执行shell脚本出错...", e);
            runningStatus = 1;
        }
        return runningStatus == 0;
    }

    /**
     * 执行cmd 命令，将执行的日志和执行状态保存在ExecShellModel对象中
     *
     * @param cmd
     * @return
     */

    public static ExecShellModel exec(String cmd, String instanceNo) {
        // ansible-playbook -i '10.10.42.13,' /root/devops_data/cd20210208154950406/execute20210208163808486/instance20210208154950410.yml
        ExecShellModel execShellModel = new ExecShellModel();
        ProcessBuilder builder = new ProcessBuilder("/bin/sh", "-c", cmd);
        builder.directory();
        int runningStatus;
        String s;
        StringBuffer sb = new StringBuffer();
        Process p = null;
        try {
            p = builder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
        assert p != null;
        try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
             BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()))) {
            while ((s = stdInput.readLine()) != null) {
                log.info("shell log info ...." + s);
                log.info("\r\n");
                writeLog(cmd, s);
                sb.append(s);
            }
            while ((s = stdError.readLine()) != null) {
                log.error("shell log error...." + s);
                log.error("\r\n");
                writeLog(cmd, s);
                sb.append(s);
            }
            try {
                runningStatus = p.waitFor();
            } catch (InterruptedException e) {
                runningStatus = 1;
                log.error("等待shell脚本执行状态时，报错...", e);
                sb.append(e.getMessage());
            }
        } catch (Exception e) {
            log.error("执行shell脚本出错...", e);
            sb.append(e.getMessage());
            runningStatus = 1;
        }
        log.info("runningStatus = " + runningStatus);
        execShellModel.setLog(sb.toString())
                .setStatus(runningStatus)
                .setInstanceNo(instanceNo);
        return execShellModel;

    }


    /**
     * 将执行日志写进文件
     */
    public static void writeLog(String cmd, String logContent) {
        log.info("---cmd:" + cmd);
        //ansible-playbook -i '10.10.5.7,' /root/devops_data/cd20210208174605113/execute20210208174608596/instance20210208174605117.yml
        String ymlPath = cmd.substring(cmd.indexOf("/"));
        String logPath = ymlPath.substring(0, ymlPath.lastIndexOf(".") + 1) + "log";
        File logFile = new File(logPath);
        if (!logFile.exists()) {
            try {
                logFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try (FileOutputStream fileOutputStream = new FileOutputStream(logFile, true)) {
            fileOutputStream.write(logContent.getBytes());
            fileOutputStream.write("\r\n".getBytes());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 连接ssh服务器
     *
     * @param user   用户名
     * @param passwd 密码
     * @param host   ip地址
     * @param port   端口
     * @return
     * @throws Exception
     */
    public static Session connect(String user, String passwd, String host, int port, String path, Integer timeOut) throws Exception {
        JSch jsch = new JSch();
        Session session;
//        if (StrUtil.isEmpty(passwd)) {
//            String pubKeyPath;
//            if (StrUtil.isEmpty(path)) {
//                pubKeyPath = "~/.ssh/id_rsa";
//            } else {
//                pubKeyPath = path;
//            }
//            jsch.addIdentity(pubKeyPath);
//        }

        session = jsch.getSession(user, host, port);

        if (session == null) {
            throw new Exception("连接失败");
        }
        session.setPassword(passwd);
        java.util.Properties config = new java.util.Properties();
        //第一次登陆
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        try {
            if (null == timeOut) {
                timeOut = 100000;
            }
            session.connect(timeOut);
        } catch (Exception e) {
            throw new Exception("连接远程端口无效或用户名密码错误");
        }
        return session;
    }

    /**
     * 远程执行shell命令并输出
     *
     * @param command
     * @param user
     * @param passwd
     * @param host
     * @param port
     * @return
     * @throws Exception
     */
    public static List<String> execCmdAndOutput(String command, String user, String passwd, String host, int port, String path, Integer timeOut) throws Exception {

        Session session = connect(user, passwd, host, port, path, timeOut);
        BufferedReader reader = null;
        Channel channel = null;
        try {
            channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);

            channel.setInputStream(null);
            ((ChannelExec) channel).setErrStream(System.err);

            channel.connect();
            InputStream in = channel.getInputStream();
            reader = new BufferedReader(new InputStreamReader(in));
            List<String> output = new ArrayList<String>();
            String buf = null;
            //返回数据
            while ((buf = reader.readLine()) != null) {
                output.add(buf);
            }
            return output;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSchException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != reader) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (null != channel) {
                channel.disconnect();
            }
            session.disconnect();
        }
        return null;
    }

}
